#ifndef _VIEW_CHANGE_HPP
#define _VIEW_CHANGE_HPP 1

#include "../messages/MacArrayMessage.hpp"
#include "../messages/HistoryDigest.hpp"
#include "../statemanagement/CheckPointState.hpp"

namespace BFT
{
	namespace order
	{
		namespace messages
		{
			
			class ViewChange: public BFT::messages::MacArrayMessage
			{
				public:
				
				ViewChange(uint32_t _view, uint32_t _ccpseq, uint32_t _scpseq, uint32_t _pseq, uint32_t _ppseq,
					   boost::shared_ptr<BFT::order::statemanagement::CheckPointState> _committedCP,
					   boost::shared_ptr<BFT::order::statemanagement::CheckPointState> _stableCP,
					   std::vector<boost::shared_ptr<BFT::messages::CertificateEntry> > _entries,
					   std::vector<boost::shared_ptr<BFT::messages::HistoryDigest> > _hist,
					   uint32_t _sendingReplica);
					   
				ViewChange(boost::shared_ptr<char> _bytes, int _bytes_size);
				
				bool equals(boost::shared_ptr<ViewChange> _other_vc);
				
				uint32_t maxCompatibleSequenceNumber(boost::shared_ptr<ViewChange> _other_vc);
				
				bool matchesCommittedCP(boost::shared_ptr<ViewChange> _other_vc);
				
				boost::shared_ptr<BFT::order::statemanagement::CheckPointState> getCommittedCP(); //inlined
				
				boost::shared_ptr<BFT::order::statemanagement::CheckPointState> getStableCP(); //inlined
				
				std::vector<boost::shared_ptr<BFT::messages::CertificateEntry> > getBatch(); //inlined
				
			 	std::vector<boost::shared_ptr<BFT::messages::HistoryDigest> > getHistories();//inlined
				
				uint32_t getCommittedCPSeqNo(); //inlined
				
				void printInfo();
				
				uint32_t getView(); //inlined
				
				uint32_t getSendingReplica(); //inlined
				
				uint32_t getStableCPSeqNo(); //inlined
				
				uint32_t getPSeqNo(); //inlined
				
				uint32_t getPPSeqNo(); //inlined
				
				protected:

				uint32_t viewNo;
				uint32_t cpSeqNo;
				uint32_t stableCPSeqNo;
				uint32_t pSeqNo;
				uint32_t ppSeqNo;
				
				boost::shared_ptr<BFT::order::statemanagement::CheckPointState> committedCP;
				boost::shared_ptr<BFT::order::statemanagement::CheckPointState> stableCP;
				std::vector<boost::shared_ptr<BFT::messages::CertificateEntry> > batch;
				std::vector<boost::shared_ptr<BFT::messages::HistoryDigest> > histories;			

				private:
				
				static uint32_t computeSize(boost::shared_ptr<BFT::order::statemanagement::CheckPointState> _committedCP,
							    boost::shared_ptr<BFT::order::statemanagement::CheckPointState> _stableCP,
							    std::vector<boost::shared_ptr<BFT::messages::CertificateEntry> > _batch 
							    );
							    
			
			};
			
			inline uint32_t ViewChange::getView() {return viewNo;}
			inline uint32_t ViewChange::getCommittedCPSeqNo() {return cpSeqNo;}
			inline uint32_t ViewChange::getStableCPSeqNo() {return stableCPSeqNo;}
			inline uint32_t ViewChange::getPSeqNo() {return pSeqNo;}
			inline uint32_t ViewChange::getPPSeqNo() {return ppSeqNo;}
			inline uint32_t ViewChange::getSendingReplica() {return getSender();}	
			inline boost::shared_ptr<BFT::order::statemanagement::CheckPointState> ViewChange::getCommittedCP() 
				{return committedCP;}
			inline boost::shared_ptr<BFT::order::statemanagement::CheckPointState> ViewChange::getStableCP() 
				{return stableCP;}
			inline std::vector<boost::shared_ptr<BFT::messages::CertificateEntry> > ViewChange::getBatch()
				{return batch;}	
			inline std::vector<boost::shared_ptr<BFT::messages::HistoryDigest> >ViewChange::getHistories()
				{return histories;}
		
		}
	}

}

#endif
